package top.glkj.hms.service.impl;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import top.glkj.hms.dao.EmployeeDao;
import top.glkj.hms.dao.UserDao;
import top.glkj.hms.dao.VipUserDao;
import top.glkj.hms.entity.*;
import top.glkj.hms.exception.DefineException;
import top.glkj.hms.service.RoleService;
import top.glkj.hms.service.UserDetailService;
import top.glkj.hms.service.UserService;
import top.glkj.hms.utils.StaticValue;
import top.glkj.hms.utils.*;

import java.lang.reflect.Field;
import java.util.*;

/**
 * @author : xgl
 * @version : 0.0.1
 * @date :2020/11/11 2:38
 */
@Slf4j
@Service
public class UserServiceImpl implements UserService {
    private final UserDao userDao;
    private final RoleService roleService;
    private final UserDetailService userDetailService;
    private final VipUserDao vipUserDao;
    private final EmployeeDao employeeDao;
    private int mapIndex = StaticValue.ZERO;

    @Autowired
    public UserServiceImpl(UserDao userDao, RoleService roleService, UserDetailService userDetailService, VipUserDao vipUserDao, EmployeeDao employeeDao) {
        this.userDao = userDao;
        this.roleService = roleService;
        this.userDetailService = userDetailService;
        this.vipUserDao = vipUserDao;
        this.employeeDao = employeeDao;
    }

    /**
     * 获取所有用户，按分页方式
     *
     * @return List<T>
     */
    @Override
    public Result getAll() {
        List<User> all = userDao.findAll();
        if (all.size() == 0) {
            return ResultFactory.isError(StaticValue.DATA_NOT_FOUND, null);
        } else {
            return ResultFactory.isSuccess(StaticValue.GET_DATA_SUCCESS, all);
        }
    }

    /**
     * 获取所有用户，按分页方式
     *
     * @param id id
     * @return Page<T>
     */
    @Override
    public Result getOne(Long id) {
        User user = userDao.findById(id).orElse(null);
        if (user == null) {
            return ResultFactory.isError(StaticValue.DATA_NOT_FOUND, null);
        } else {
            return ResultFactory.isSuccess(StaticValue.GET_DATA_SUCCESS, user);
        }
    }

    /**
     * 修改或者保存
     *
     * @param user T t
     * @return true or false
     */
    @Override
    public Result save(User user) {
        try {
            User save = userDao.save(user);
            return ResultFactory.isSuccess(StaticValue.SUCCESS_MESSAGE, save);
        } catch (Exception e) {
            log.error(e.getMessage());
            return ResultFactory.isError(StaticValue.ERROR_MESSAGE, null);
        }
    }

    /**
     * 彻底从数据库中删除实体{T}
     *
     * @param user T t
     * @return true or false
     */
    @Override
    public Result delete(User user) {
        try {
            userDao.delete(user);
            return ResultFactory.isSuccess(StaticValue.DELETE_DATA_ERROR);
        } catch (Exception e) {
            log.error(e.getMessage());
            return ResultFactory.isError(StaticValue.ERROR_MESSAGE);
        }
    }

    /**
     * 标记删除
     *
     * @param user T t
     * @return true or false
     */
    @Override
    public Result remove(User user) {
        user.setDel(true);
        user.setStatus(Status.Delete);
        ArrayList<String> list = new ArrayList<>();
        list.add("status");
        list.add("del");
        Result save = updateUser(user,list);
        if (ResultFactory.isSuccess(save)) {
            return ResultFactory.isSuccess(StaticValue.DELETE_DATA_SUCCESS, save);
        } else {
            return ResultFactory.isException(StaticValue.DELETE_DATA_ERROR);
        }
    }

    /**
     * Locates the user based on the username. In the actual implementation, the search
     * may possibly be case sensitive, or case insensitive depending on how the
     * implementation instance is configured. In this case, the <code>UserDetails</code>
     * object that comes back may have a username that is of a different case than what
     * was actually requested..
     *
     * @param username the username identifying the user whose data is required.
     * @return a fully populated user record (never <code>null</code>)
     * @throws UsernameNotFoundException if the user could not be found or the user has no
     *                                   GrantedAuthority
     */
    @Override
    public User loadUserByUsername(String username) throws UsernameNotFoundException {
        User userByUsername = userDao.findUserByUsername(username);
        if (userByUsername == null) {
            throw new UsernameNotFoundException("未查询到用户名为【" + username + "】的用户");
        }
        return userByUsername;
    }

    /**
     * 分页查询
     *
     * @param page 当前页码
     * @param size 页面大小
     * @return page User
     */
    @Override
    public Result getAllUserByPageAndSize(int page, int size) {
        GlUtils<User, UserDao> glUtils = new GlUtils<>();
        return glUtils.getAllByPageAndSize(page, size, userDao);
    }

    /**
     * 分页条件查询
     *
     * @param page    当前页码
     * @param size    页面大小
     * @param argName 参数名
     * @param value   参数值
     * @return page User
     */
    @Override
    public Result getAllUserByPageAndSizeAndArgs(int page, int size, String argName, String value) {
        GlUtils<User, UserDao> glUtils = new GlUtils<>();
        return glUtils.getAllByPageAndSizeAndArgs(page, size, argName, value, userDao);
    }

    /**
     * 分页查询
     *
     * @param page 当前页码
     * @param size 页面大小
     * @param args 参数键值对
     * @return page User
     */
    @Override
    public Result getAllUserByPageAndSizeAndAnyArgs(int page, int size, Map<String, String> args) {
        GlUtils<User, UserDao> glUtils = new GlUtils<>();
        return glUtils.getAllByPageAndSizeAndAnyArgs(page, size, args, userDao);

    }

    /**
     * 根据用户获取用户的资源
     *
     * @param user 用户
     * @return 资源
     */
    @Override
    public Result getAllResourceByUser(User user) {
        Set<Resource> resources = new HashSet<>();
        User user1 = userDao.findById(user.getId()).orElse(null);
        if (user1 != null) {
            Set<Role> roles = user1.getRoles();
            Set<Permission> permissions = new HashSet<>();
            for (Role role : roles) {
                permissions.addAll(role.getPermissions());
                for (Permission permission : permissions) {
                    resources.addAll(permission.getResources());
                }
            }
        }
        return ResultFactory.isSuccess(StaticValue.GET_DATA_SUCCESS, new ArrayList<>(resources));
    }

    /**
     * 保存用户角色
     *
     * @param user  用户
     * @param roles 角色列表
     * @return 执行结果
     */
    @Override
    public Result saveUserRoles(User user, List<Role> roles) {
        user.setRoles(new HashSet<>(roles));
        return save(user);
    }


    /**
     * 添加新用户
     *
     * @param user 用户
     * @return true or false
     */
    @Override
    public Result addUser(User user) {
        if (userDao.findUserByUsername(user.getUsername()) != null) {
            return ResultFactory.isError("该用户名已被添加");
        }
        user.setUpdateTime(new Date());
        user.setCreateUserId(getCurrentUser().getId());
        //user.setStatus(Status.Enable);
        user.setDel(false);
        user.setPassword(new BCryptPasswordEncoder().encode(user.getPassword()));
        user.setCreateTime(new Date());
        HashSet<Role> roles = new HashSet<>();
        for (Role role : user.getRoles()) {
            Result one = roleService.getOne(role.getId());
            if (ResultFactory.isSuccess(one)) {
                roles.add((Role) one.getObject());
            } else {
                return one;
            }
        }
        user.setRoles(roles);
        user.setUserDetail(null);
        return save(user);
    }

    /**
     * 修改密码
     *
     * @param id          用户id
     * @param password    用户旧密码
     * @param newPassWord 用户新密码
     * @param code        验证码
     * @return 修改结果
     */
    @Override
    public Result updatePassWord(Long id, String password, String newPassWord, String code) {
        User user = userDao.findById(id).orElse(null);
        if (user != StaticValue.NULL) {
            BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
            if (encoder.matches(user.getPassword(), password)) {
                return getResult(id, newPassWord, encoder);
            } else {
                return ResultFactory.isError(StaticValue.COMPARE_PASSWORD_FAIL);
            }
        }
        return ResultFactory.isError(StaticValue.USERNAME_NOTFOUND);
    }

    /**
     * 修改密码
     *
     * @param id          用户id
     * @param newPassWord 用户新密码
     * @return 修改结果
     */
    @Override
    public Result updatePassWord(Long id, String newPassWord) {
        User user = userDao.findById(id).orElse(null);
        if (user != StaticValue.NULL) {
            BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
            return getResult(id, newPassWord, encoder);
        }
        return ResultFactory.isError(StaticValue.USER_NOTFOUND);
    }

    private Result getResult(Long id, String newPassWord, BCryptPasswordEncoder encoder) {
        try {
            userDao.updatePassWord(id, encoder.encode(newPassWord));
            return ResultFactory.isSuccess(StaticValue.UPDATE_DATA_SUCCESS);
        } catch (Exception e) {
            log.error(e.getMessage());
            return ResultFactory.isError(StaticValue.UPDATE_DATA_ERROR);
        }
    }

    /**
     * 修改密码
     *
     * @param ids         用户id
     * @param newPassWord 用户新密码
     * @return 修改结果
     */
    @Override
    @Transactional(rollbackFor = {DefineException.class})
    public Result updateAllPassWord(List<Long> ids, String newPassWord) throws DefineException {
        try {
            int updateAllPassWord = userDao.updateAllPassWord(ids, newPassWord);
            if (updateAllPassWord == ids.size()) {
                userDao.flush();
                return ResultFactory.isSuccess(StaticValue.UPDATE_DATA_SUCCESS);
            } else {
                throw new DefineException(StaticValue.UPDATE_DATA_ERROR);
            }
        } catch (Exception e) {
            log.error(e.getMessage());
            throw new DefineException(StaticValue.UPDATE_DATA_ERROR);
        }
    }

    /**
     * 根据参数名修改用户
     *
     * @param user   用户信息
     * @param fields 参数名
     * @return result
     */
    @Override
    public Result updateUser(User user, List<String> fields) {
        Result result = getOne(user.getId());
        if (ResultFactory.isSuccess(result)) {
            User object = (User) result.getObject();
            Field[] fields1 = object.getClass().getDeclaredFields();
            int size = 0;
            for (Field field : fields1) {
                if (size == fields.size()) {
                    break;
                }
                if (fields.contains(field.getName())) {
                    try {
                        field.setAccessible(true);
                        Field declaredField = user.getClass().getDeclaredField(field.getName());
                        declaredField.setAccessible(true);
                        //System.out.println(declaredField.get(user));
                        //System.out.println(field.get(object));
                        //System.out.println(declaredField.get(user));
                        field.set(
                    object   , declaredField.get(user)
                        );
                    } catch (Exception e) {
                        e.printStackTrace();
                        return ResultFactory.isException(StaticValue.UPDATE_IS_EXCEPTION);
                    }
                    size++;
                }
            }
            try {
                if (size == 0) {
                    return ResultFactory.isError(StaticValue.NOT_UPDATE_DATA);
                }
                User save = userDao.save(object);
                return ResultFactory.isSuccess(StaticValue.UPDATE_DATA_SUCCESS, save);
            } catch (Exception e) {
                log.error(e.getMessage());
                return ResultFactory.isError(StaticValue.UPDATE_DATA_ERROR);
            }
        } else {
            return result;
        }
    }

    /**
     * 新增角色
     *
     * @param uid  用户id
     * @param rids 角色id列表
     * @return 修改结果
     */
    @Override
    @Transactional(rollbackFor = {DefineException.class})
    public Result userAddRole(Long uid, List<Long> rids) throws DefineException {
        Result one = getOne(uid);
        if (ResultFactory.isSuccess(one)) {
            User user = (User) one.getObject();
            for (Long rid : rids) {
                Result one1 = roleService.getOne(rid);
                if (ResultFactory.isSuccess(one1)) {
                    user.getRoles().add((Role) one1.getObject());
                } else {
                    throw new DefineException(StaticValue.NOT_ROLE_DATA);
                }
            }
            return save(user);
        } else {
            return one;
        }
    }

    /**
     * 修改或移除角色
     *
     * @param uid  用户id
     * @param rids 角色id列表
     * @return 修改结果
     * @throws DefineException e
     */
    @Override
    public Result userUpdateRole(Long uid, List<Long> rids) throws DefineException {
        Result one = getOne(uid);
        if (ResultFactory.isSuccess(one)) {
            User user = (User) one.getObject();
            HashSet<Role> roles = new HashSet<>();
            for (Long rid : rids) {
                Result one1 = roleService.getOne(rid);
                if (ResultFactory.isSuccess(one1)) {
                    roles.add((Role) one1.getObject());
                } else {
                    throw new DefineException(StaticValue.NOT_ROLE_DATA);
                }
            }
            user.setRoles(roles);
            return save(user);
        } else {
            return one;
        }
    }

    /**
     * 获取新注册的用户
     *
     * @return
     */
    @Override
    public int getCountNewUser() {
        return 0;
    }

    /**
     * 用户添加用户详情
     *
     * @param user       用户信息
     * @param userDetail 用户详情
     * @return 结果
     */
    @Override
    public Result userAddUserDetail(User user, UserDetail userDetail) {
        return null;
    }

    /**
     * 用户更新用户详情
     *
     * @param user       用户信息
     * @param userDetail 用户详情
     * @return
     */
    @Override
    public Result userUpdateUserDetail(User user, UserDetail userDetail) {
        user.setUserDetail(userDetail);
        List<String> field = new ArrayList<>();
        field.add("userDetail");
        return updateUser(user, field);
    }

    /**
     * 查询vip 用户
     *
     * @param user 用户信息
     * @return 用户详情
     */
    @Override
    public Result getVipUserByUser(User user) {
        VipUser users = vipUserDao.findVipUsersByUser(user);
        return getNotNullBaseEntity(users);
    }

    /**
     * 查询vip 用户
     *
     * @return vip 用户
     */
    @Override
    public Result getAllVipUser() {
        List<VipUser> all = vipUserDao.findAll();
        return getNotEmptyAll(all);
    }

    /**
     * 分页获取所有vip
     *
     * @param page
     * @param size
     * @return vip 用户
     */
    @Override
    public Result getAllVipUserByPageAndSize(int page, int size) {
        GlUtils<VipUser, VipUserDao> glUtils = new GlUtils<>();
        return glUtils.getAllByPageAndSize(page, size, vipUserDao);
    }

    /**
     * 添加vip
     *
     * @param vipUser vip 用户
     * @return vip 用户
     */
    @Override
    public Result addVipUser(VipUser vipUser) {
        vipUser.setCreateUserId(getCurrentUser().getId());
        vipUser.setUpdateUserId(getCurrentUser().getId());
        vipUser.setDel(false);
        vipUser.setUpdateTime(new Date());
        vipUser.setCreateTime(new Date());
        try {
            VipUser save = vipUserDao.save(vipUser);
            return ResultFactory.isSuccess(StaticValue.ADD_DATA_SUCCESS, save);
        }catch (Exception e){
            return ResultFactory.isException(StaticValue.ADD_DATA_ERROR, e);
        }
    }

    /**
     * 修改vip
     *
     * @param vipUser vip 用户
     * @return vip 用户
     */
    @Override
    public Result updateVipUser(VipUser vipUser) {
        vipUser.setUpdateUserId(getCurrentUser().getId());
        vipUser.setUpdateTime(new Date());
        try {
            VipUser save = vipUserDao.save(vipUser);
            return ResultFactory.isSuccess(StaticValue.UPDATE_DATA_SUCCESS, save);
        }catch (Exception e){
            return ResultFactory.isException(StaticValue.UPDATE_DATA_ERROR, e);
        }


    }

    /**
     * 删除vip
     *
     * @param vipUser vip 用户
     * @return vip 用户
     */
    @Override
    public Result deleteVipUser(VipUser vipUser) {
        try {
            vipUserDao.delete(vipUser);
            return ResultFactory.isSuccess(StaticValue.DELETE_DATA_SUCCESS);
        }catch (Exception e){
            return ResultFactory.isException(StaticValue.DELETE_DATA_ERROR, e);
        }
    }

    /**
     * 移除vip
     *
     * @param vipUser vip 用户
     * @return vip 用户
     */
    @Override
    public Result removeVipUser(VipUser vipUser) {
        vipUser.setDel(true);
        return updateVipUser(vipUser);
    }

    /**
     * 查询Employee 用户
     *
     * @param user 用户信息
     * @return 用户详情
     */
    @Override
    public Result getEmployeeByUser(User user) {
        Employee employee = employeeDao.findEmployeeByUser(user);
        return getNotNullBaseEntity(employee);
    }

    /**
     * 查询Employee 用户
     *
     * @return Employee 用户
     */
    @Override
    public Result getAllEmployeeUser() {
        return getNotEmptyAll(employeeDao.findAll());
    }

    /**
     * 分页获取所有Employee
     *
     * @param page
     * @param size
     * @return Employee 用户
     */
    @Override
    public Result getAllEmployeeUserByPageAndSize(int page, int size) {
        GlUtils<Employee,EmployeeDao> glUtils = new GlUtils<>();
        return glUtils.getAllByPageAndSize(page,size,employeeDao);
    }

    /**
     * 添加Employee
     *
     * @param employee Employee 用户
     * @return Employee 用户
     */
    @Override
    public Result addEmployee(Employee employee) {
        employee.setCreateUserId(getCurrentUser().getId());
        employee.setUpdateUserId(getCurrentUser().getId());
        employee.setDel(false);
        employee.setUpdateTime(new Date());
        employee.setCreateTime(new Date());
        try {
            Employee save = employeeDao.save(employee);
            return ResultFactory.isSuccess(StaticValue.ADD_DATA_SUCCESS, save);
        }catch (Exception e){
            return ResultFactory.isException(StaticValue.ADD_DATA_ERROR, e);
        }
    }

    /**
     * 修改Employee
     *
     * @param employee Employee 用户
     * @return Employee 用户
     */
    @Override
    public Result updateEmployee(Employee employee) {
        employee.setUpdateUserId(getCurrentUser().getId());
        employee.setUpdateTime(new Date());
        try {
            Employee save = employeeDao.save(employee);
            return ResultFactory.isSuccess(StaticValue.UPDATE_DATA_SUCCESS, save);
        }catch (Exception e){
            return ResultFactory.isException(StaticValue.UPDATE_DATA_ERROR, e);
        }
    }

    /**
     * 删除Employee
     *
     * @param employee Employee 用户
     * @return Employee 用户
     */
    @Override
    public Result deleteEmployee(Employee employee) {
        try {
            employeeDao.delete(employee);
            return ResultFactory.isSuccess(StaticValue.DELETE_DATA_SUCCESS);
        }catch (Exception e){
            return ResultFactory.isException(StaticValue.DELETE_DATA_ERROR, e);
        }
    }

    /**
     * 移除Employee
     *
     * @param employee Employee 用户
     * @return Employee 用户
     */
    @Override
    public Result removeEmployee(Employee employee) {
        employee.setDel(true);
        return updateEmployee(employee);
    }
}
